<?php
/**
 * Возвращает комменты в виде древовидного списка
 *
 * {{!tree_comments commentList as='comments'}}
 *
 * примерно вот такого вида:
 *
 * [                       // список комментов первого уровня
 *   [comment_fields] +
 *   'comments': [         // список вложенных комментов
 *     [comment_fields +
 *       'comments': [
 *         ...
 *       ]
 *     ]
 *   ],
 *   [comment_fields] +
 *   'comments': [
 *     [comment_fields]
 *   ],
 * ]
 *
 *
 * предполагается, что структуры комментов содержат поля {oid, parent_oid}, задающие
 * родительско-детское отношене между ними.
 *
 */

$l_source = $params[0];
$a_node_id   = 'oid';        // имя атрибута, содержащего id узла
$a_parent_id = 'parent_oid'; // имя атрибута, содержащего parent_id узла
$a_tree_name = isset($params['as']) ? $params['as'] : 'comments'; // имя атрибута для поддеревьев

// пробежим по исходному списку и соберем все записи в map { node_id : record }
$m_nodes = array();
foreach ($l_source as &$record) {
	$node_id = $record[$a_node_id];

	$m_nodes[$node_id] =& $record;
} unset($record); // на всякий случай

// пробежим по записям и соберем все в дерево
$tree = array();
foreach ($m_nodes as $node_id => &$record) {
	$parent_id = $record[$a_parent_id];

	if (isset($m_nodes[$parent_id])) { // помещаем запись в подерево родителю
		$m_nodes[$parent_id][$a_tree_name][$node_id] =& $record;
	} else { // если родителя нет, помещаем запись в корень дерева.
		// хотя бы для одной записи в исходном списке не будет родителя
		$tree[$node_id] =& $record;
	}
} unset($record); // на всякий случай

// на самом деле, дерево можно строить одним циклом, т.к. известно, что в
// исходном списке родители всегда появляются раньше детей.

return $tree;
?>
